home *** CD-ROM | disk | FTP | other *** search
/ T&A 2 the Maxx 3 / T and A 2 The Maxx Number 3.iso / viewers / unixview / xgl17dta.z / xgl17dta / readfiles.c < prev    next >
C/C++ Source or Header  |  1991-07-24  |  32KB  |  1,315 lines

  1. #ident "@(#)readfiles.c    1.12 91/04/03 XGRASP"
  2. /*-
  3.  * readfiles.c - routines to load images, fonts, and execution files.
  4.  *
  5.  * Copyright (c) 1991 by Patrick J. Naughton
  6.  *
  7.  * Permission to use, copy, modify, and distribute this software and its
  8.  * documentation for any purpose and without fee is hereby granted,
  9.  * provided that the above copyright notice appear in all copies and that
  10.  * both that copyright notice and this permission notice appear in
  11.  * supporting documentation.
  12.  *
  13.  * This file is provided AS IS with no warranties of any kind.  The author
  14.  * shall have no liability with respect to the infringement of copyrights,
  15.  * trade secrets or any patents by this file or any part thereof.  In no
  16.  * event will the author be liable for any lost revenue or profits or
  17.  * other special, indirect and consequential damages.
  18.  *
  19.  * Comments and additions should be sent to the author:
  20.  *
  21.  *                     Patrick J. Naughton
  22.  *                     Sun Microsystems
  23.  *                     2550 Garcia Ave, MS 10-20
  24.  *                     Mountain View, CA 94043
  25.  *                     (415) 336-1080
  26.  *
  27.  */
  28.  
  29. #include "grasp.h"
  30.  
  31. ImageStruct *image[MAXIMAGES];
  32. int         numimages = 0;
  33. FontStruct *font[MAXFONTS];
  34. int         numfonts = 0;
  35. ExecStruct *exec[MAXEXECS];
  36. int         numexecs = 0;
  37.  
  38. extern ImageStruct *readgifimage();
  39.  
  40. void
  41. lowerstr(s)
  42.     char       *s;
  43. {
  44.     while (*s) {
  45.     if (*s >= 'A' && *s <= 'Z')
  46.         *s = *s + 'a' - 'A';
  47.     s++;
  48.     }
  49. }
  50.  
  51. void
  52. hexdump(fp, n)
  53.     FILE       *fp;
  54.     int         n;
  55. {
  56.     long        ofs = ftell(fp);
  57.     int         i, j;
  58.     u_char      b[16];
  59.  
  60.     for (j = 0; j < n; j++) {
  61.     for (i = 0; i < 16; i++) {
  62.         b[i] = GetByte(fp);
  63.         printf("%02x ", b[i]);
  64.     }
  65.     printf(" ");
  66.     for (i = 0; i < 16; i++)
  67.         printf("%c ", isprint(b[i]) ? b[i] : '.');
  68.     printf("\n");
  69.     }
  70.     fseek(fp, ofs, 0);
  71. }
  72.  
  73. /*-
  74.         Border                                 Color Table
  75.         Color    Color       Palette   1            2              3
  76.         -----    -----       ------- -----------------------------------
  77.           0      Black          0    Green        Red             Brown
  78.           1      Blue           1    Cyan         Magenta         White
  79.           2      Green          2    Cyan         Red             White
  80.           3      Cyan           3    Bright Green Bright Red      Yellow
  81.           4      Red            4    Bright Cyan  Bright Magenta  White
  82.           5      Magenta        5    Bright Cyan  Bright Red      White
  83.           6      Brown       -------------------------------------------
  84.           7      Grey
  85.           8      Dark Grey (Bright Black)
  86.           9      Bright Blue
  87.          10      Bright Green
  88.          11      Bright Cyan
  89.          12      Bright Red
  90.          13      Bright Magenta
  91.          14      Yellow (Bright Brown)
  92.          15      White (Bright Grey)
  93. */
  94.  
  95. u_short     egapal[16][3] = {
  96.     {0x0000, 0x0000, 0x0000}, {0x0000, 0x0000, 0xaaaa},
  97.     {0x0000, 0xaaaa, 0x0000}, {0x0000, 0xaaaa, 0xaaaa},
  98.     {0xaaaa, 0x0000, 0x0000}, {0xaaaa, 0x0000, 0xaaaa},
  99.     {0xaaaa, 0x5555, 0x0000}, {0xaaaa, 0xaaaa, 0xaaaa},
  100.     {0x5555, 0x5555, 0x5555}, {0x5555, 0x5555, 0xffff},
  101.     {0x5555, 0xffff, 0x5555}, {0x5555, 0xffff, 0xffff},
  102.     {0xffff, 0x5555, 0x5555}, {0xffff, 0x5555, 0xffff},
  103.     {0xffff, 0xffff, 0x5555}, {0xffff, 0xffff, 0xffff}
  104. };
  105.  
  106. int         cgapal[3][6] = {
  107.     {2, 3, 3, 10, 11, 11},
  108.     {4, 5, 4, 12, 13, 12},
  109.     {6, 15, 15, 14, 15, 15}
  110. };
  111.  
  112.  
  113. Colormap
  114. CreateEGAcmap()
  115. {
  116.     Colormap    cmap;
  117.     XColor      colors[16];
  118.     u_long      pixels[16];
  119.     u_long      pmasks;
  120.     int         i;
  121.  
  122.     cmap = XCreateColormap(dsp, win, vis, AllocNone);
  123.     XAllocColorCells(dsp, cmap, True, &pmasks, 0, pixels, 16);
  124.     for (i = 0; i < 16; i++) {
  125.     colors[i].pixel = pixels[i];
  126.     colors[i].red = egapal[i][0];
  127.     colors[i].green = egapal[i][1];
  128.     colors[i].blue = egapal[i][2];
  129.     colors[i].flags = DoRed | DoGreen | DoBlue;
  130.     }
  131.     XStoreColors(dsp, cmap, colors, 16);
  132.     return cmap;
  133. }
  134.  
  135. int
  136. findext(s)
  137.     char       *s;
  138. {
  139.     int         i;
  140.     static char *exts[] = {
  141.     "pic", "pcx", "pal", "clp", "gif", "set", "fnt", "txt"
  142.     };
  143.     static int  extcodes[] = {
  144.     EXT_PIC, EXT_PCX, EXT_PAL, EXT_CLP, EXT_GIF, EXT_SET, EXT_FNT, EXT_TXT
  145.     };
  146.  
  147.     ++s;   /* get past the dot */
  148.     for (i = 0; i < (sizeof exts / sizeof exts[0]); i++)
  149.     if (!strcmp(s, exts[i]))
  150.         return extcodes[i];
  151.     return -1;
  152. }
  153.  
  154. void
  155. stringtofont(ex, i)
  156.     ExecStruct *ex;
  157. {
  158.     int         k;
  159.     char       *s = strtok(ex->Code[i].val.s, ".");
  160.     lowerstr(s);
  161.     for (k = 0; k < numfonts; k++) {
  162.     if (!strcmp(font[k]->name, s)) {
  163.         free(ex->Code[i].val.s);
  164.         ex->Code[i].token = FONTTYPE;
  165.         ex->Code[i].val.font = font[k];
  166.         break;
  167.     }
  168.     }
  169.     if (k == numfonts) {
  170.     printf("font \"%s\" referenced but not in directory.\n", s);
  171.     ex->Code[i].token = FONTTYPE;
  172.     ex->Code[i].val.font = 0;
  173.     }
  174. }
  175.  
  176. void
  177. stringtoimage(ex, i, deftype)
  178.     ExecStruct *ex;
  179.     int         i;
  180.     int         deftype;
  181. {
  182.     int         k;
  183.     char       *s = strtok(ex->Code[i].val.s, ".");
  184.     char       *ext = strrchr(ex->Code[i].val.s, '.');
  185.     if (ext) {
  186.     int         extcode = findext(ext);
  187.     for (k = 0; k < numimages; k++) {
  188.         if (!strcmp(image[k]->name, s) && image[k]->type == extcode) {
  189.         free(ex->Code[i].val.s);
  190.         ex->Code[i].token = IMAGE;
  191.         ex->Code[i].val.image = image[k];
  192.         break;
  193.         }
  194.     }
  195.     } else {
  196.     for (k = 0; k < numimages; k++) {
  197.         if (!strcmp(image[k]->name, s)) {
  198.         /*
  199.          * this might be the second time through here, so don't free
  200.          * the string more than once...
  201.          */
  202.         if (ex->Code[i].token == STRING) {
  203.             free(ex->Code[i].val.s);
  204.             ex->Code[i].token = IMAGE;
  205.         }
  206.         ex->Code[i].val.image = image[k];
  207.         if (image[k]->type == deftype)
  208.             break;
  209.         }
  210.     }
  211.     }
  212.     if (ex->Code[i].token != IMAGE)
  213.     error("%s: image \"%s\" referenced but not in directory.\n", s);
  214. }
  215.  
  216. void
  217. stringtolabel(ex, i)
  218.     ExecStruct *ex;
  219.     int         i;
  220. {
  221.     int         k;
  222.     char       *s = strtok(ex->Code[i].val.s, ".");
  223.     lowerstr(s);
  224.     for (k = 0; k < ex->numlabels; k++) {
  225.     if (!strcmp(s, ex->label[k].string)) {
  226.         free(ex->Code[i].val.s);
  227.         ex->Code[i].token = INTEGER;
  228.         ex->Code[i].val.i = ex->label[k].ipaddr;
  229.         break;
  230.     }
  231.     if (k == ex->numlabels)
  232.         error("%s: label \"%s\" referenced but not found.\n", s);
  233.     }
  234. }
  235.  
  236. void
  237. stringtoexec(ex, i)
  238.     ExecStruct *ex;
  239.     int         i;
  240. {
  241.     int         k;
  242.     char       *s = strtok(ex->Code[i].val.s, ".");
  243.     lowerstr(s);
  244.     for (k = 0; k < numexecs; k++) {
  245.     if (!strcmp(exec[k]->name, s)) {
  246.         free(ex->Code[i].val.s);
  247.         ex->Code[i].token = EXECTYPE;
  248.         ex->Code[i].val.exec = exec[k];
  249.         break;
  250.     }
  251.     }
  252.     if (k == numexecs)
  253.     error("%s: exec \"%s\" referenced but not in directory.\n", s);
  254. }
  255.  
  256.  
  257. int
  258. calcwidth(data, width, height, left)
  259.     u_char     *data;
  260.     int         width;
  261.     int         height;
  262.     int        *left;
  263. {
  264.     int         bpsl = (width + 7) >> 3;
  265.     int         right;
  266.     int         mask;
  267.     int         i;
  268.     int         j;
  269.  
  270. /*find left */
  271.     *left = 0;
  272.     for (i = 0; i < bpsl; i++) {
  273.     for (mask = 0x80; mask > 0; mask >>= 1) {
  274.         for (j = 0; j < height; j++) {
  275.         if (data[j * bpsl + i] & mask)
  276.             goto calcright;
  277.         }
  278.         (*left)++;
  279.     }
  280.     }
  281.     *left = 0;
  282.     return width / 2;    /* must be the space char... */
  283.  
  284. calcright:/* find right */
  285.  
  286.     right = bpsl * 8;
  287.     for (i = bpsl - 1; i >= 0; i--) {
  288.     for (mask = 0x01; mask < 0x100; mask <<= 1) {
  289.         for (j = 0; j < height; j++) {
  290.         if (data[j * bpsl + i] & mask)
  291.             return right - *left;
  292.         }
  293.         right--;
  294.     }
  295.     }
  296.     error("%s: bad width calc.");
  297. }
  298.  
  299.  
  300. FontStruct *
  301. readfont(fp, dirent)
  302.     FILE       *fp;
  303.     FilenameStruct *dirent;
  304. {
  305.     FontStruct *font;
  306.     XImage      xim;
  307.     int         first;
  308.     int         num;
  309.     int         datasize;
  310.     int         i;
  311.     char       *data;
  312.  
  313.     fseek(fp, dirent->offset, 0);
  314.     font = (FontStruct *) malloc(sizeof(FontStruct));
  315.     font->name = strtok(strdup(dirent->fname), ".");
  316.     (void) GetLong(fp);    /* skip file length */
  317.     (void) GetWord(fp);    /* skip length */
  318.     if (imverbose)
  319.     hexdump(fp, 4);
  320.     num = GetByte(fp);
  321. /* hack for trashed fonts... */
  322.     if (num == -1) {
  323.     free(font->name);
  324.     free(font);
  325.     return (FontStruct *) 0;
  326.     }
  327.     first = GetByte(fp);
  328.     font->width = GetByte(fp);
  329.     font->height = GetByte(fp);
  330.     datasize = GetByte(fp);
  331.     data = (char *) malloc(datasize);
  332.     if (!data)
  333.     error("%s: couldn't malloc glyph memory\n");
  334.     if (verbose)
  335.     fprintf(stderr, "%s: (FNT) %d %dx%d,%d(%d) glyphs, from %d to %d\n",
  336.         font->name, num, font->width, font->height,
  337.         datasize, font->height * ((font->width + 7) >> 3),
  338.         first, first + num - 1);
  339.  
  340.     xim.height = font->height;
  341.     xim.width = font->width;
  342.     xim.depth = 1;
  343.     xim.xoffset = 0;
  344.     xim.format = XYBitmap;
  345.     xim.data = data;
  346.     xim.byte_order = MSBFirst;
  347.     xim.bitmap_unit = 8;
  348.     xim.bitmap_bit_order = MSBFirst;
  349.     xim.bitmap_pad = 8;
  350.     xim.bytes_per_line = (font->width + 7) / 8;
  351.  
  352.     for (i = 0; i < 256; i++) {
  353.     if (i >= first && i < first + num) {
  354.         fread(data, datasize, 1, fp);
  355.         font->glyphs[i].width = calcwidth(data, font->width, font->height,
  356.                           &font->glyphs[i].lbearing);
  357.         font->glyphs[i].pix = XCreatePixmap(dsp, win,
  358.                         font->width, font->height, 1);
  359.         XPutImage(dsp, font->glyphs[i].pix, gc1, &xim, 0, 0, 0, 0,
  360.               font->width, font->height);
  361.     } else {
  362.         font->glyphs[i].pix = (Pixmap) 0;
  363.         font->glyphs[i].width = 0;
  364.         font->glyphs[i].lbearing = 0;
  365.     }
  366.     }
  367.     free(data);
  368.  
  369.     return font;
  370. }
  371.  
  372.  
  373. FontStruct *
  374. readset(fp, dirent)
  375.     FILE       *fp;
  376.     FilenameStruct *dirent;
  377. {
  378.     FontStruct *font;
  379.     XImage      xim;
  380.     int         first;
  381.     int         num;
  382.     int         datasize;
  383.     int         i;
  384.     char       *data;
  385.     char        fontname[14];
  386.     int         type;
  387.     int         checktype;
  388.     int         fontascent;
  389.     int         proportional;
  390.     int         bpsl;
  391.     int         lfgap;
  392.     int         italics;
  393.     int         fntinvert;
  394.     int         fnthbold;
  395.     int         fntvbold;
  396.     int         fnthmag;
  397.     int         fntvmag;
  398.     int         fnthfract;
  399.     int         fntvfract;
  400.     int         fntdirection;
  401.     int         fntrot90;
  402.     int         fnthflip;
  403.     int         fntvflip;
  404.     int         fntcolor;
  405.     int         fntsubtype;
  406.     char        unused[18];
  407.     int         dataofs;
  408.  
  409.     int         celloffs[256];
  410.     int         cellwidth[256];
  411.  
  412.     fseek(fp, dirent->offset, 0);
  413.  
  414.     (void) GetLong(fp);    /* skip file length */
  415.  
  416.     if (imverbose)
  417.     hexdump(fp, 4);
  418.  
  419.     /* non-compressed type = 0x10 or compressed type = 0x14 */
  420.     type = GetByte(fp);
  421.     if (type != 0x10 && type != 0x14)
  422.     return readfont(fp, dirent);
  423.  
  424.     fread(fontname, 13, 1, fp);
  425.     fontname[13] = 0;
  426.     /* non-compressed font = 0xba, compressed font = 0xdc */
  427.     checktype = GetByte(fp);
  428.  
  429.     font = (FontStruct *) malloc(sizeof(FontStruct));
  430.     font->name = strtok(strdup(dirent->fname), ".");
  431.  
  432.     fontascent = GetByte(fp);
  433.     num = GetByte(fp);
  434.     /* limited to the lower 94 ASCII characters: 0x21 - 0x7E */
  435.     first = GetByte(fp) + 0x20;
  436.     proportional = GetByte(fp);    /* 0 = non-proportional */
  437.     font->width = GetByte(fp);
  438.     font->height = GetByte(fp);
  439.     bpsl = GetByte(fp);
  440.     datasize = font->height * bpsl;
  441.     spacegap = GetByte(fp);
  442.     chargap = GetByte(fp);
  443.     lfgap = GetByte(fp);
  444.     (void) GetWord(fp);    /* skip file length */
  445.     italics = GetByte(fp);
  446.  
  447.     fntinvert = GetByte(fp);    /* 0 = dont invert, 1 = invert */
  448.     fnthbold = GetByte(fp);    /* number of overlapping bits horizontal */
  449.     fntvbold = GetByte(fp);    /* number of overlapping bits vertical */
  450.     fnthmag = GetByte(fp);    /* integral horizontal bit magnification */
  451.     fntvmag = GetByte(fp);    /* integral vertical bit magnification */
  452.     fnthfract = GetByte(fp);    /* fractional horizontal bit magnification */
  453.     fntvfract = GetByte(fp);    /* fractional vertical bit magnification */
  454.     fntdirection = GetByte(fp);    /* Print direction 0 = left to right, 1...3 =
  455.                  * counterclock 1...3 */
  456.     fntrot90 = GetByte(fp);    /* rotation 0 = up, 1...3 = counterclock 1...3 */
  457.     fnthflip = GetByte(fp);    /* horizontal flip 0 = no, 1 = yes */
  458.     fntvflip = GetByte(fp);    /* vertical flip 0 = no, 1 = yes */
  459.     fntcolor = GetByte(fp);    /* color of font */
  460.     fntsubtype = GetByte(fp);    /* subcategory type of this font */
  461.     fread(unused, 18, 1, fp);
  462.  
  463.     if (verbose)
  464.     fprintf(stderr, "%s[%s]: (SET) %d %dx%d,%d %sglyphs, from %d to %d\n",
  465.         font->name, fontname, num, font->width, font->height, datasize,
  466.         proportional ? "var-" : "fixed-", first, first + num - 1);
  467.  
  468.     if (type == 0x10) {
  469.     for (i = 0; i <= num; i++)
  470.         celloffs[i] = GetWord(fp);
  471.     if (proportional) {
  472.         for (i = 0; i <= num; i++)
  473.         cellwidth[i] = GetByte(fp);
  474.     }
  475.     dataofs = ftell(fp) - dirent->offset + 4;
  476.     data = (char *) malloc(datasize * num);
  477.     if (!data)
  478.         error("%s: couldn't malloc glyph memory\n");
  479.     fread(data, num, datasize, fp);
  480.  
  481.     xim.width = font->width;
  482.     xim.height = font->height;
  483.     xim.depth = 1;
  484.     xim.xoffset = 0;
  485.     xim.format = XYBitmap;
  486.     xim.data = 0;
  487.     xim.byte_order = MSBFirst;
  488.     xim.bitmap_unit = 8;
  489.     xim.bitmap_bit_order = MSBFirst;
  490.     xim.bitmap_pad = 8;
  491.     xim.bytes_per_line = bpsl;
  492.  
  493.     for (i = 0; i < 256; i++) {
  494.         font->glyphs[i].pix = (Pixmap) 0;
  495.         font->glyphs[i].width = 0;
  496.         font->glyphs[i].lbearing = 0;
  497.     }
  498.  
  499.     for (i = 0; i <= num; i++) {
  500.         int         j = first + i - 1;
  501.  
  502.         font->glyphs[j].lbearing = 0;
  503.         font->glyphs[j].width = proportional ? cellwidth[i] : font->width;
  504.         font->glyphs[j].pix = XCreatePixmap(dsp, win,
  505.                       font->glyphs[j].width, font->height, 1);
  506.         xim.data = &data[celloffs[i] - dataofs];
  507.         XPutImage(dsp, font->glyphs[j].pix, gc1, &xim, 0, 0, 0, 0,
  508.               font->glyphs[j].width, font->height);
  509.     }
  510.     free(data);
  511.     } else {
  512.     printf("dont do compressed SET's yet.\n");
  513.     }
  514.     return font;
  515. }
  516.  
  517.  
  518. ImageStruct *
  519. readimage(fp, dirent, filetype)
  520.     FILE       *fp;
  521.     FilenameStruct *dirent;
  522.     int         filetype;
  523. {
  524.     ImageStruct *im;
  525.     XImage     *xim;
  526.     int         i;
  527.     int         j;
  528.     int         format;
  529.     int         bpsl;
  530.     int         blocks;
  531.     int         datasize;
  532.     long        blockoffset;
  533.     u_char     *ptr;
  534.     int         bpp;
  535.     int         planes;
  536.     int         idx;
  537.     int         magic;
  538.     int         unknown;
  539.     int         type;
  540.     int         edesc;
  541.     int         exsize;
  542.     int         maxcolorval;
  543.     u_long      pixels[256];
  544.     u_long      pmasks;
  545.     int         filelen;
  546.  
  547.     im = (ImageStruct *) malloc(sizeof(ImageStruct));
  548.  
  549.     fseek(fp, dirent->offset, 0);
  550.  
  551.     filelen = GetLong(fp);    /* length of whole image file... */
  552.  
  553.     if (imverbose)
  554.     hexdump(fp, 4);
  555.  
  556.     im->name = strtok(strdup(dirent->fname), ".");
  557.     im->type = filetype;
  558.  
  559.     magic = GetWord(fp);
  560.     if (magic != 0x1234) {    /* I'm guessing here */
  561.     im->w = GetWord(fp);
  562.     im->h = GetWord(fp);
  563.     printf("%dx%d %d, %d, %d, %d\n", im->w, im->h, im->w * im->h / 4,
  564.            magic - 6, ((im->w + 3) >> 2) * im->h, filelen - 6);
  565.     im->xoff = 0;
  566.     im->yoff = 0;
  567.     bpp = 2;
  568.     planes = 1;
  569.     type = 'a';
  570.     edesc = 1;
  571.     exsize = 0;
  572.     } else {
  573.     im->w = GetWord(fp);
  574.     im->h = GetWord(fp);
  575.     im->xoff = GetWord(fp);
  576.     im->yoff = GetWord(fp);
  577.     bpp = GetByte(fp);
  578.     planes = ((bpp & 0xf0) >> 4) + 1;
  579.     bpp &= 0x0f;
  580.     if (GetByte(fp) != 0xff)
  581.         error("%s: %s is corrupt\n", im->name);
  582.     type = GetByte(fp);
  583.     edesc = GetWord(fp);
  584.     exsize = GetWord(fp);
  585.     }
  586.  
  587.     if (bpp == 1 && planes == 1) {
  588.     im->d = 1;
  589.     format = XYBitmap;
  590.     bpsl = (im->w + 7) >> 3;
  591.     XSetForeground(dsp, gc, white);
  592.     XSetBackground(dsp, gc, black);
  593.     } else {
  594.     im->d = 8;
  595.     format = ZPixmap;
  596.     bpsl = im->w;
  597.     }
  598.     datasize = bpsl * im->h;
  599.     ptr = (u_char *) malloc(datasize);
  600.     if (!ptr)
  601.     error("%s: malloc failed on image data.\n");
  602.  
  603.     if (verbose)
  604.     printf(
  605.      "%s: (PIC) %dx%dx%d(%1x:%1x) [%d,%d] sz=%d t=%c edesc=%02x ext=%d\n",
  606.            im->name,
  607.            im->w,
  608.            im->h,
  609.            im->d,
  610.            bpp, planes,
  611.            im->xoff,
  612.            im->yoff,
  613.            datasize,
  614.            type,
  615.            edesc,
  616.            exsize);
  617.  
  618.     if (edesc != 0)
  619.     im->cmap = XCreateColormap(dsp, win, vis, AllocNone);
  620.  
  621.     switch (edesc) {
  622.     case 0:
  623.     im->cmaplen = 0;
  624.     im->cmap = (Colormap) 0;
  625.     break;
  626.     case 1:
  627.     im->cmaplen = 4;
  628.     break;
  629.     case 2:
  630.     im->cmaplen = 16;
  631.     maxcolorval = 15;
  632.     break;
  633.     case 3:
  634.     im->cmaplen = 16;
  635.     maxcolorval = 63;
  636.     break;
  637.     case 4:
  638.     im->cmaplen = 256;
  639.     maxcolorval = 63;
  640.     break;
  641.     case 5:
  642.     im->cmaplen = 16;
  643.     maxcolorval = 63;
  644.     break;
  645.     default:
  646.     error("%s: bad edesc: %d\n", edesc);
  647.     }
  648.  
  649.     if (im->cmaplen > 0)
  650.     XAllocColorCells(dsp, im->cmap, True, &pmasks, 0, pixels, im->cmaplen);
  651.  
  652.     switch (edesc) {
  653.     case 0:
  654.     break;
  655.     case 1:
  656.     {
  657.         char        pal;
  658.  
  659.         if (exsize != 2)
  660.         error("%s: unexpected esize: %d\n", exsize);
  661.         pal = GetByte(fp);
  662.         j = GetByte(fp);
  663.         i = 0;
  664.         im->colors[i].pixel = pixels[i];
  665.         im->colors[i].red = egapal[j][0];
  666.         im->colors[i].green = egapal[j][1];
  667.         im->colors[i].blue = egapal[j][2];
  668.         im->colors[i].flags = DoRed | DoGreen | DoBlue;
  669.         for (i = 1; i < im->cmaplen; i++) {
  670.         j = cgapal[i - 1][pal];
  671.         im->colors[i].pixel = pixels[i];
  672.         im->colors[i].red = egapal[j][0];
  673.         im->colors[i].green = egapal[j][1];
  674.         im->colors[i].blue = egapal[j][2];
  675.         im->colors[i].flags = DoRed | DoGreen | DoBlue;
  676.         }
  677.     }
  678.     break;
  679.     case 2:
  680.     case 3:
  681.     if (exsize != im->cmaplen)
  682.         error("%s: bad exsize: %d\n", exsize);
  683.     for (i = 0; i < im->cmaplen; i++) {
  684.         int         pal = GetByte(fp);
  685.         im->colors[i].pixel = pixels[i];
  686.         im->colors[i].red = decodepal(pal, 0x20, 0x04) << 8;
  687.         im->colors[i].green = decodepal(pal, 0x10, 0x02) << 8;
  688.         im->colors[i].blue = decodepal(pal, 0x08, 0x01) << 8;
  689.         im->colors[i].flags = DoRed | DoGreen | DoBlue;
  690.     }
  691.     break;
  692.     case 4:
  693.     case 5:
  694.     if (exsize != 0 && exsize != im->cmaplen * 3)
  695.         printf("bad exsize: %d\n", exsize);
  696.     for (i = 0; i < im->cmaplen; i++) {
  697.         im->colors[i].pixel = pixels[i];
  698.         im->colors[i].red = (GetByte(fp) * 255 / maxcolorval) << 8;
  699.         im->colors[i].green = (GetByte(fp) * 255 / maxcolorval) << 8;
  700.         im->colors[i].blue = (GetByte(fp) * 255 / maxcolorval) << 8;
  701.         im->colors[i].flags = DoRed | DoGreen | DoBlue;
  702.     }
  703.     break;
  704.     }
  705.  
  706.     if (edesc > 0) {
  707.     if (imverbose) {
  708.         printf("%d colors\n", im->cmaplen);
  709.         for (i = 0; i < im->cmaplen; i++) {
  710.         printf("%02x%02x%02x ",
  711.                im->colors[i].red >> 8,
  712.                im->colors[i].green >> 8,
  713.                im->colors[i].blue >> 8);
  714.         if (!((i + 1) % 8))
  715.             printf("\n");
  716.         }
  717.     }
  718.     XStoreColors(dsp, im->cmap, im->colors, im->cmaplen);
  719.     }
  720.     if (magic != 0x1234) {    /* BSAVE */
  721.     fread(ptr, filelen - 6, 1, fp);
  722.     } else {
  723.     blocks = GetWord(fp);
  724.     if (blocks == 0) {
  725.         if (imverbose)
  726.         printf("unpacked data\n");
  727.         fread(ptr, datasize, 1, fp);
  728.     } else {
  729.  
  730.         if (imverbose) {
  731.         printf("%d image blocks\n", blocks);
  732.         hexdump(fp, 4);
  733.         }
  734.         blockoffset = ftell(fp);
  735.         idx = 0;
  736.         for (i = 0; i < blocks; i++) {
  737.         u_char      esc;
  738.         int         rlebytes;
  739.         int         bufsize;
  740.  
  741.         fseek(fp, blockoffset, 0);
  742.  
  743.         rlebytes = GetWord(fp);
  744.         bufsize = GetWord(fp);
  745.         esc = GetByte(fp);
  746.  
  747.         blockoffset += rlebytes;
  748.  
  749.         if (imverbose) {
  750.             printf("block: %d (len = %d) (bufsize = %d) (esc = %d)\n",
  751.                i, rlebytes, bufsize, esc);
  752.             hexdump(fp, 4);
  753.         }
  754.         rlebytes -= 5;
  755.         while (rlebytes) {
  756.             u_char      c = GetByte(fp);
  757.             rlebytes--;
  758.             if (c == esc) {
  759.             u_int       count = GetByte(fp);
  760.             rlebytes--;
  761.             if (count == 0) {
  762.                 count = GetWord(fp);
  763.                 rlebytes -= 2;
  764.             }
  765.             c = GetByte(fp);
  766.             rlebytes--;
  767. #if 1
  768.             if (idx + count > datasize) {
  769.                 fprintf(stderr, "*");
  770.                 goto bailimage;
  771.             }
  772. #endif
  773.             memset(&ptr[idx], c, count);
  774.             idx += count;
  775.             } else {
  776. #if 1
  777.             if (idx + 1 > datasize) {
  778.                 fprintf(stderr, "*");
  779.                 goto bailimage;
  780.             }
  781. #endif
  782.             ptr[idx] = c;
  783.             idx++;
  784.             }
  785.         }
  786.         }
  787.     }
  788.     }
  789. bailimage:
  790.  
  791.     switch (bpp) {
  792.     case 1:
  793.     switch (planes) {
  794.     case 1:
  795.         break;
  796.     case 2:
  797.     case 3:
  798.         error("%s: %d plane decoding not implemented\n", planes);
  799.         break;
  800.     case 4:
  801.         {
  802.         u_char     *dst;
  803.         u_char     *src;
  804.         u_char     *old;
  805.         int         srcbpsl = (im->w + 7) >> 3;
  806.         int         plane0 = srcbpsl * 0 * im->h;
  807.         int         plane1 = srcbpsl * 1 * im->h;
  808.         int         plane2 = srcbpsl * 2 * im->h;
  809.         int         plane3 = srcbpsl * 3 * im->h;
  810.  
  811.         src = old = ptr;
  812.         dst = ptr = (u_char *) malloc(datasize);
  813.  
  814.         if (!dst)
  815.             error("%s: malloc failed on image data.\n");
  816.  
  817.         for (j = 0; j < im->h; j++) {
  818.             int         mask = 0x80;
  819.             int         addr = j * srcbpsl;
  820.             for (i = 0; i < im->w; i++, mask >>= 1) {
  821.             if (mask == 0) {
  822.                 mask = 0x80;
  823.                 addr++;
  824.             }
  825.             *dst++ = ((src[plane0 + addr] & mask) != 0) +
  826.                 2 * ((src[plane1 + addr] & mask) != 0) +
  827.                 4 * ((src[plane2 + addr] & mask) != 0) +
  828.                 8 * ((src[plane3 + addr] & mask) != 0);
  829.             }
  830.         }
  831.         free(old);
  832.         }
  833.         break;
  834.     }
  835.     break;
  836.     case 2:
  837.     switch (planes) {
  838.     case 1:
  839.         {
  840.         u_char     *dst;
  841.         u_char     *src;
  842.         u_char     *old;
  843.         int         rem;
  844.  
  845.         src = old = ptr;
  846.         dst = ptr = (u_char *) malloc(datasize);
  847.  
  848.         if (!dst)
  849.             error("%s: malloc failed on image data.\n");
  850.  
  851.         rem = im->w & 3;
  852.         for (i = 0; i < im->h; i++) {
  853.             for (j = 0; j < im->w >> 2; j++) {
  854.             *dst++ = *src >> 6 & 3;
  855.             *dst++ = *src >> 4 & 3;
  856.             *dst++ = *src >> 2 & 3;
  857.             *dst++ = *src >> 0 & 3;
  858.             src++;
  859.             }
  860.             switch (rem) {
  861.             case 3:
  862.             dst[2] = *src >> 2 & 3;
  863.             case 2:
  864.             dst[1] = *src >> 4 & 3;
  865.             case 1:
  866.             dst[0] = *src >> 6 & 3;
  867.             src++;
  868.             dst += rem;
  869.             case 0:
  870.             break;
  871.             }
  872.         }
  873.         free(old);
  874.         }
  875.         break;
  876.     default:
  877.         error("%s: %d plane decoding not implemented\n", planes);
  878.         break;
  879.     }
  880.     break;
  881.     case 4:
  882.     {
  883.         u_char     *dst;
  884.         u_char     *src;
  885.         u_char     *old;
  886.  
  887.         src = old = ptr;
  888.         dst = ptr = (u_char *) malloc(datasize);
  889.  
  890.         if (!dst)
  891.         error("%s: malloc failed on image data.\n");
  892.  
  893.         for (i = 0; i < im->h; i++) {
  894.         for (j = 0; j < im->w / 2; j++) {
  895.             *dst++ = *src >> 4 & 0xf;
  896.             *dst++ = *src >> 0 & 0xf;
  897.             src++;
  898.         }
  899.         }
  900.         free(old);
  901.     }
  902.     break;
  903.     case 8:
  904.     break;
  905.     }
  906.  
  907. /* invert the image top to bottom */
  908.     {
  909.     u_char     *buffer;
  910.     buffer = (u_char *) malloc(bpsl);
  911.     for (i = 0; i < im->h / 2; i++) {
  912.         memcpy(buffer, ptr + (im->h - i - 1) * bpsl, bpsl);
  913.         memcpy(ptr + (im->h - i - 1) * bpsl, ptr + i * bpsl, bpsl);
  914.         memcpy(ptr + i * bpsl, buffer, bpsl);
  915.     }
  916.     free(buffer);
  917.     }
  918.     xim = XCreateImage(dsp, vis, im->d, format, 0, ptr, im->w, im->h, 8, bpsl);
  919.     im->pix = XCreatePixmap(dsp, win, im->w, im->h, 8);
  920.     XPutImage(dsp, im->pix, gc, xim, 0, 0, 0, 0, im->w, im->h);
  921.     XSync(dsp, False);
  922.     return im;
  923. }
  924.  
  925.  
  926. ImageStruct *
  927. readpcximage(fp, dirent)
  928.     FILE       *fp;
  929.     FilenameStruct *dirent;
  930. {
  931.     ImageStruct *im;
  932.     XImage     *xim;
  933.     int         i;
  934.     int         j;
  935.     u_char      pcxhd[128];
  936.     int         magic;
  937.     int         version;
  938.     int         encoded;
  939.     int         bpp;
  940.     int         xmin, ymin, xmax, ymax;
  941.     int         planes;
  942.     int         bpsl;
  943.  
  944.     int         datasize;
  945.     u_char     *ptr;
  946.     int         maxcolorval;
  947.     u_long      pixels[256];
  948.     u_long      pmasks;
  949.     int         filelen;
  950.     int         format;
  951.  
  952.     im = (ImageStruct *) malloc(sizeof(ImageStruct));
  953.  
  954.     fseek(fp, dirent->offset, 0);
  955.  
  956.     filelen = GetLong(fp);    /* length of whole image file... */
  957.  
  958.     if (imverbose)
  959.     hexdump(fp, 4);
  960.  
  961.     im->name = strtok(strdup(dirent->fname), ".");
  962.     im->type = EXT_PCX;
  963.  
  964.     fread(pcxhd, 128, 1, fp);
  965.     magic = pcxhd[0];
  966.     if (magic != 0x0a)
  967.     printf("I don't think this is really a .pcx file!\n");
  968.     version = pcxhd[1];
  969.     encoded = pcxhd[2];
  970.     xmin = pcxhd[4] + (256 * pcxhd[5]);
  971.     ymin = pcxhd[6] + (256 * pcxhd[7]);
  972.     xmax = pcxhd[8] + (256 * pcxhd[9]);
  973.     ymax = pcxhd[10] + (256 * pcxhd[11]);
  974.     im->w = xmax - xmin + 1;
  975.     im->h = ymax - ymin + 1;
  976.     im->xoff = im->yoff = 0;
  977.     bpsl = pcxhd[66] + (256 * pcxhd[67]);
  978.     bpp = pcxhd[3];
  979.     planes = pcxhd[65];
  980.  
  981.     if (bpp == 1 && planes == 1) {
  982.     im->d = 1;
  983.     format = XYBitmap;
  984.     XSetForeground(dsp, gc, white);
  985.     XSetBackground(dsp, gc, black);
  986.     } else {
  987.     im->d = 8;
  988.     format = ZPixmap;
  989.     bpsl = im->w;
  990.     }
  991.     datasize = bpsl * im->h;
  992.     ptr = (u_char *) malloc(datasize);
  993.     if (!ptr)
  994.     error("%s: malloc failed on image data.\n");
  995.  
  996.     if (verbose)
  997.     printf("%s: (PCX) %dx%dx%d(%1x:%1x) [%d,%d] sz=%d ver=%d enc=%d\n",
  998.            im->name,
  999.            im->w,
  1000.            im->h,
  1001.            im->d,
  1002.            bpp, planes,
  1003.            im->xoff,
  1004.            im->yoff,
  1005.            datasize,
  1006.            version,
  1007.            encoded);
  1008.  
  1009.     if (version != 0)
  1010.     im->cmap = XCreateColormap(dsp, win, vis, AllocNone);
  1011.  
  1012.     switch (version) {
  1013.     case 0:
  1014.     case 3:
  1015.     im->cmaplen = 0;
  1016.     im->cmap = (Colormap) 0;
  1017.     break;
  1018.     case 2:
  1019.     im->cmaplen = 16;
  1020.     maxcolorval = 255;
  1021.     break;
  1022.     case 5:
  1023.     im->cmaplen = 256;
  1024.     maxcolorval = 255;
  1025.     break;
  1026.     case 1:
  1027.     case 4:
  1028.     default:
  1029.     error("%s: bad pcx version: %d\n", version);
  1030.     }
  1031.  
  1032.     if (im->cmaplen > 0)
  1033.     XAllocColorCells(dsp, im->cmap, True, &pmasks, 0, pixels, im->cmaplen);
  1034.  
  1035.     switch (version) {
  1036.     case 0:
  1037.     case 3:
  1038.     break;
  1039.     case 2:    /* I'm guessing here! */
  1040.     for (i = 0; i < im->cmaplen; i++) {
  1041.         im->colors[i].pixel = pixels[i];
  1042.         im->colors[i].red = pcxhd[16 + i + 0] << 8;
  1043.         im->colors[i].green = pcxhd[16 + i + 1] << 8;
  1044.         im->colors[i].blue = pcxhd[16 + i + 2] << 8;
  1045.         im->colors[i].flags = DoRed | DoGreen | DoBlue;
  1046.     }
  1047.     break;
  1048.     case 5:
  1049.     fseek(fp, dirent->offset + filelen + 4 - 769, 0);
  1050.     if (GetByte(fp) != 12)
  1051.         printf("I don't think this is a VGA palette.\n");
  1052.     for (i = 0; i < im->cmaplen; i++) {
  1053.         im->colors[i].pixel = pixels[i];
  1054.         im->colors[i].red = GetByte(fp) << 8;
  1055.         im->colors[i].green = GetByte(fp) << 8;
  1056.         im->colors[i].blue = GetByte(fp) << 8;
  1057.         im->colors[i].flags = DoRed | DoGreen | DoBlue;
  1058.     }
  1059.     fseek(fp, dirent->offset + 4 + 128, 0);
  1060.     break;
  1061.     }
  1062.  
  1063.     if (version > 0) {
  1064.     if (imverbose) {
  1065.         printf("%d colors\n", im->cmaplen);
  1066.         for (i = 0; i < im->cmaplen; i++) {
  1067.         printf("%02x%02x%02x ",
  1068.                im->colors[i].red >> 8,
  1069.                im->colors[i].green >> 8,
  1070.                im->colors[i].blue >> 8);
  1071.         if (!((i + 1) % 8))
  1072.             printf("\n");
  1073.         }
  1074.     }
  1075.     XStoreColors(dsp, im->cmap, im->colors, im->cmaplen);
  1076.     }
  1077.     if (encoded) {
  1078.     /*
  1079.      * Goes like this: Read a byte.  If the two high bits are set, then the
  1080.      * low 6 bits contain a repeat count, and the byte to repeat is the
  1081.      * next byte in the file.  If the two high bits are not set, then this
  1082.      * is the byte to write.
  1083.      */
  1084.  
  1085.     int         i = 0;
  1086.  
  1087.     while (i < datasize) {
  1088.         int         byte = GetByte(fp);
  1089.         if ((byte & 0xc0) == 0xc0) {
  1090.         int         count = byte & 0x3f;
  1091.         int value = GetByte(fp);
  1092.         if (i + count > datasize)
  1093.             count = datasize - i - 1;    /* catch overflow */
  1094.         memset(ptr + i, value, count);
  1095.         i += count;
  1096.         } else {
  1097.         ptr[i++] = byte;
  1098.         }
  1099.     }
  1100.     } else
  1101.     fread(ptr, datasize, 1, fp);
  1102.  
  1103.     /*
  1104.      * need to do planar -> chunky conversion here if we support > 1 plane pcx
  1105.      * files.
  1106.      */
  1107.  
  1108.     xim = XCreateImage(dsp, vis, im->d, format, 0, ptr, im->w, im->h, 8, bpsl);
  1109.     im->pix = XCreatePixmap(dsp, win, im->w, im->h, 8);
  1110.     XPutImage(dsp, im->pix, gc, xim, 0, 0, 0, 0, im->w, im->h);
  1111.     XSync(dsp, False);
  1112.     return im;
  1113. }
  1114.  
  1115.  
  1116. void
  1117. printcodes(ex)
  1118.     ExecStruct *ex;
  1119. {
  1120.     int         i;
  1121.     for (i = 0; i < ex->numcodes; i++) {
  1122.     printf("%4d: ", i);
  1123.     if (ex->Code[i].token < NTOKENS)
  1124.         printf("[TOK] %s (%d) (%d args)\n",
  1125.            tokens[ex->Code[i].token], ex->Code[i].token,
  1126.            ex->Code[i].val.i);
  1127.     else {
  1128.         switch (ex->Code[i].token) {
  1129.         case INTEGER:
  1130.         printf("[INT] %d\n", ex->Code[i].val.i);
  1131.         break;
  1132.         case STRING:
  1133.         printf("[STR] \"%s\"\n", ex->Code[i].val.s);
  1134.         break;
  1135.         case IMAGE:
  1136.         printf("[IMG] \"%s\"\n", ex->Code[i].val.image->name);
  1137.         break;
  1138.         case FONTTYPE:
  1139.         printf("[FNT] \"%s\"\n", ex->Code[i].val.font->name);
  1140.         break;
  1141.         case EXECTYPE:
  1142.         printf("[EXC] \"%s\"\n", ex->Code[i].val.exec->name);
  1143.         break;
  1144.         case WILDTYPE:
  1145.         printf("[WLD] \"@\"\n");
  1146.         break;
  1147.         default:
  1148.         error("%s: printcodes bogosity (%d)\n", ex->Code[i].token);
  1149.         }
  1150.     }
  1151.     }
  1152.     printf("labels:\n");
  1153.     for (i = 0; i < ex->numlabels; i++)
  1154.     printf("[LABEL] \"%s\" %d\n", ex->label[i].string, ex->label[i].ipaddr);
  1155. }
  1156.  
  1157.  
  1158. /* turn all cload and pload args into pointers to the
  1159.  * actual image structure instead of the filename
  1160.  * turn all fload args into pointers to the font structure
  1161.  * instead of the filename, and change the '@' string to a WILDTYPE.
  1162.  */
  1163. void
  1164. converttypes(ex)
  1165.     ExecStruct *ex;
  1166. {
  1167.     int         i, j;
  1168.     for (i = 0; i < ex->numcodes; i++) {
  1169.     int         t = ex->Code[i].token;
  1170.     char       *s = ex->Code[i].val.s;
  1171.     char        nargs = ex->Code[i].val.i;
  1172.  
  1173.     switch (t) {
  1174.     case STRING:
  1175.         if (s[0] == '@' && s[1] == 0) {
  1176.         ex->Code[i].token = WILDTYPE;
  1177.         ex->Code[i].val.i = 0;
  1178.         }
  1179.         break;
  1180.     case FLOAD:
  1181.         stringtofont(ex, i + 1);
  1182.         break;
  1183.     case CLOAD:
  1184.         stringtoimage(ex, i + 1, EXT_CLP);
  1185.         break;
  1186.     case PLOAD:
  1187.         stringtoimage(ex, i + 1, EXT_PIC);
  1188.         break;
  1189.     case LINK:
  1190.     case CALL:
  1191.         stringtoexec(ex, i + 1);
  1192.         if (nargs > 1)
  1193.         stringtolabel(ex, i + 2);
  1194.         break;
  1195.     case DATABEGIN:
  1196.     case GOTO:
  1197.     case GOSUB:
  1198.         stringtolabel(ex, i + 1);
  1199.         break;
  1200.     case IFKEY:
  1201.         for (j = 2; j <= nargs; j += 2)
  1202.         stringtolabel(ex, i + j);
  1203.         break;
  1204.     case IFMEM:
  1205.     case IFVIDEO:
  1206.     case WAITKEY:
  1207.         if (nargs > 1)
  1208.         stringtolabel(ex, i + 2);
  1209.         break;
  1210.     }
  1211.     }
  1212. }
  1213.  
  1214. ExecStruct *
  1215. readtxt(fp, dir)
  1216.     FILE       *fp;
  1217.     FilenameStruct *dir;
  1218. {
  1219.     ExecStruct *ex;
  1220.     int         len;
  1221.     char       *txt;
  1222.     int         i;
  1223.  
  1224.     ex = (ExecStruct *) malloc(sizeof(ExecStruct));
  1225.     ex->name = strtok(strdup(dir->fname), ".");
  1226.  
  1227.     fseek(fp, dir->offset, 0);
  1228.     len = GetLong(fp);
  1229.     len &= 0x00ffffff;    /* hack */
  1230.     ex->txt = (char *) malloc(len + 1);
  1231.     fread(ex->txt, len, 1, fp);
  1232.     ex->txt[len] = 26;
  1233.     if (showtext)
  1234.     puts(ex->txt);
  1235.     return ex;
  1236. }
  1237.  
  1238.  
  1239. void
  1240. readfiles(fp, dir, count)
  1241.     FILE       *fp;
  1242.     FilenameStruct *dir;
  1243.     int         count;
  1244. {
  1245.     int         i;
  1246.  
  1247.     for (i = 0; i < count; i++) {
  1248.     char       *p = strrchr(dir[i].fname, '.');
  1249.     int         extcode;
  1250.     if (!p)
  1251.         error("%s: %s has no extension.\n", dir[i].fname);
  1252.     extcode = findext(p);
  1253.     switch (extcode) {
  1254.     case EXT_PCX:
  1255.         image[numimages++] = readpcximage(fp, &dir[i]);
  1256.         break;
  1257.     case EXT_PIC:
  1258.     case EXT_CLP:
  1259.     case EXT_PAL:
  1260.         image[numimages++] = readimage(fp, &dir[i], extcode);
  1261.         break;
  1262.     case EXT_GIF:
  1263.         image[numimages++] = readgifimage(fp, &dir[i]);
  1264.         break;
  1265.     case EXT_SET:
  1266.         font[numfonts++] = readset(fp, &dir[i]);
  1267.         if (font[numfonts - 1] == (FontStruct *) 0)
  1268.         --numfonts;
  1269.         break;
  1270.     case EXT_FNT:
  1271.         font[numfonts++] = readfont(fp, &dir[i]);
  1272.         if (font[numfonts - 1] == (FontStruct *) 0)
  1273.         --numfonts;
  1274.         break;
  1275.     case EXT_TXT:
  1276.         exec[numexecs++] = readtxt(fp, &dir[i]);
  1277.         break;
  1278.     default:
  1279.         printf("skipping %s: unknown extension.\n", dir[i].fname);
  1280.     }
  1281.     }
  1282.  
  1283.     for (i = 0; i < numexecs; i++) {
  1284.     ExecStruct *ex = exec[i];
  1285.     parsefile(ex, ex->txt);
  1286.     converttypes(ex);
  1287.     if (printthecodes)
  1288.         printcodes(ex);
  1289.     }
  1290.  
  1291.     if (imageloop) {
  1292.     int         im = 0;
  1293.     XMapWindow(dsp, win);
  1294.     XSync(dsp, False);
  1295.     while (1) {
  1296.         XEvent      ev;
  1297.         XNextEvent(dsp, &ev);
  1298.         if (ev.type == ButtonPress) {
  1299.         if (++im >= numimages)
  1300.             im = 0;
  1301.         if (((XButtonEvent *) & ev)->button == Button3)
  1302.             break;
  1303.         XStoreName(dsp, win, image[im]->name);
  1304.         XSetWindowColormap(dsp, win, image[im]->cmap);
  1305.         XCopyArea(dsp, image[im]->pix, win, gc,
  1306.               0, 0,
  1307.               image[im]->w,
  1308.               image[im]->h,
  1309.               0, 0);
  1310.  
  1311.         }
  1312.     }
  1313.     }
  1314. }
  1315.